<script setup lang="ts">
import * as echarts from 'echarts';
import { ref, watch, nextTick, markRaw, withDefaults } from 'vue'
import { PlusCircleOutlined } from '@ant-design/icons-vue';
import {categoryData} from "~/logic";
import { message } from 'ant-design-vue';
import { markerDataType } from '../market'
import { rangesType, newRangesType } from './priceChart'

interface CustomOption extends echarts.EChartsCoreOption {
  dataset: {
    source: newRangesType;
  };
}

const [messageApi, contextHolder] = message.useMessage();

const props = withDefaults(defineProps<{
  dataSource: markerDataType[]
}>(), {
})


const myEchart = ref<echarts.ECharts | null>(null)
const optionRangesArr = ref<string[]>([])
const totalProductCount = ref(0)
const totalSellerCount = ref(0)
const totalPaymentCount = ref(0)
const showChart = ref(false)
const rangesValue = ref<number[]>([])
const sourceRangesValue = ref<number[]>([])
const init = ref(true)
const selectValue = ref(-1)
const selectOption = ref()
const filterList = ref<markerDataType[]>([])

const option = ref<CustomOption>({
  legend: {},
  tooltip: {
    trigger: 'item',
    axisPointer: {
      type: 'shadow'
    },
    formatter: function (params: echarts.TooltipComponentFormatterCallbackParams) {
       if (Array.isArray(params)) return
       let content = '';
       if (Array.isArray(params.value)) {
          content += `<div>${params.value[0]}</div>`; // 顶部价格区间
          content += `<div style="margin-top: 10px;">`;
          // 商品数
          content += `<div style="color: #5470c6;">商品数: ${params.value[4]} / ${params.value[1]}%</div>`;
          // 卖家数
          content += `<div style="color: #91cc75;">卖家数: ${params.value[5]} / ${params.value[2]}%</div>`;
          // 付款人数
          content += `<div style="color: #fac858;">付款人数: ${params.value[6]} / ${params.value[3]}%</div>`;
          content += `</div>`;
       }
      return content;
    }
  },
  dataset: {
    source: [[]]
  },
  xAxis: { type: 'category' },
  yAxis: { show: false },
  series: [
    { type: 'bar', name: '商品数' },
    { type: 'bar', name: '卖家数' },
    { type: 'bar', name: '付款人数' }
  ]
})

const initRangesValue = () => {
  const unique = Array.from(new Set((filterList.value as markerDataType[]).map(obj => obj.priceWap))).map(priceWap => {  
    return (filterList.value as markerDataType[]).find(obj => obj.priceWap === priceWap);
  });
  unique.sort((a: markerDataType | undefined, b: markerDataType | undefined) => {
    if (!a || !b) {
      return 0;
    }
    if (a.priceWap < b.priceWap) {
      return -1;
    }
    if (a.priceWap > b.priceWap) {
      return 1;
    }
    return 0;
  });
   if (unique.length === 0) return
  // 第一个和最后一个对象的 现价
  let firstPriceWap = Number(unique[0]?.priceWap);
  let lastPriceWap = Number(unique[unique.length - 1]?.priceWap);
  // 过滤出剩余可选的对象（不包括第一个和最后一个对象）
  let availableObjects = unique.filter(obj => Number(obj?.priceWap) !== firstPriceWap && Number(obj?.priceWap) !== lastPriceWap);
  // 随机选择4个对象的 id
  let randomPriceWaps = [] as number[];
  while (randomPriceWaps.length < 4) {
    let randomIndex = Math.floor(Math.random() * availableObjects.length);
    let randomId = Number(availableObjects[randomIndex]?.priceWap);
    if (randomId !== undefined && !randomPriceWaps.includes(randomId)) {
      randomPriceWaps.push(randomId as number); // 将 randomId 转换为 number 类型
    }
  }
  // 将第一个和最后一个对象的 priceWap 加入到随机选择的 priceWap 数组中
  randomPriceWaps.push(firstPriceWap, lastPriceWap);
  // 去重和排序
  randomPriceWaps = Array.from(new Set(randomPriceWaps)).sort((a, b) => a - b);
  rangesValue.value = randomPriceWaps;
  sourceRangesValue.value = randomPriceWaps
  // 设置 || 更新图标区间
  upDateOptionRangesArr()
}

// 创建二维数组
const generate2DArray = (ranges: typeof optionRangesArr.value):rangesType => {
  return ranges.map((range) => {
    return [range, 0, 0, 0, 0, 0, 0]; // 多了三列用于存储原始值
  });
}
// 设置柱状图数据
const setDataSource = (type = 'init') => {
  const sourceArr: rangesType = generate2DArray(optionRangesArr.value)
  const sellerArr: string[] = []
  totalProductCount.value = 0
  totalSellerCount.value = 0
  totalPaymentCount.value = 0
  // 遍历数组
  const set = (item: markerDataType) => {
    optionRangesArr.value.forEach((element, index) => {
      const staPrice = +(element.split('~')[0])
      const endPrice = +(element.split('~')[1])
      const itemPriceWap = typeof item.priceWap === 'string' ? parseFloat(item.priceWap) : item.priceWap;
      const itemRealSales = typeof item.realSales === 'string' ? parseInt(item.realSales.match(/\d+/)?.[0] || '0') : item.realSales || 0;
      if (itemPriceWap >= staPrice && itemPriceWap < endPrice) {
        sourceArr[index][1]++ // 商品数
        totalProductCount.value++
        sourceArr[index][3] += itemRealSales // 付款人数
        totalPaymentCount.value += itemRealSales
        if (!sellerArr.includes(item.userId)) {
          sellerArr.push(item.userId)
          sourceArr[index][2]++ // 卖家数
          totalSellerCount.value++
        }
      }
    })
  }
  filterList.value.forEach((item) => {
    set(item)
  })
  // 计算百分比，并保存原始值
  sourceArr.forEach((row, index) => {
    row[4] = row[1] // 原始商品数
    row[5] = row[2] // 原始卖家数
    row[6] = row[3] // 原始付款人数
    row[1] = +((row[1] / totalProductCount.value) * 100).toFixed(0) // 百分比商品数
    row[2] = +((row[2] / totalSellerCount.value) * 100).toFixed(0) // 百分比卖家数
    row[3] = +((row[3] / totalPaymentCount.value) * 100).toFixed(0) // 百分比付款人数
  })
  option.value.dataset.source = [
    ['产品', '商品数', '卖家数', '付款人数', '',],
    ...sourceArr
  ]
  nextTick(() => {
    showChart.value = true
    if (type == 'init') {
      myEchart.value =  markRaw(echarts.init( document.getElementById('myEchart')));
      init.value = false
    }
    if (myEchart.value) {
      myEchart.value.setOption(option.value, true);
      myEchart.value.resize(); // 强制重绘图表
    }
  })
}

// 更新规则数组
const upDateOptionRangesArr = () => {
  const arr = []
  for (let i = 0; i < rangesValue.value.length; i++) {
    if (i + 1 < rangesValue.value.length) {
      arr.push(`${rangesValue.value[i]}~${rangesValue.value[i + 1]}`)
    }
  }
  optionRangesArr.value = arr
  // 更新图表数据
  if (init.value) return
  setDataSource('update')
}

// 设置范围区间规则
const setRangesValue = (value: number, index: number) => {
  if (rangesValue.value.length === 0) {
    initRangesValue()
    return
  }
  // 上一个值
  const last = +(rangesValue.value[index - 1])
  // 当前值
  const atPresent = +(rangesValue.value[index])
  // 下一个值
  const next = +(rangesValue.value[index + 1])
  // 如果跟上一个值相等，就当前值+1
  if (atPresent === last) {
    rangesValue.value[index] = atPresent + 1
  }
  // 如果跟下一个值相等, 或者比下一值大，就当前值-1
  if(atPresent === next || atPresent > next) {
    rangesValue.value[index] = atPresent - 1
  }
  // 比上一个值大，就当前值-1
  if(atPresent < last) {
    rangesValue.value[index] = last + 1
  }
  // 比下一值大，就当前值-1
  if(atPresent > next) {
    rangesValue.value[index] = next - 1
  }
  for (let i = 0; i < rangesValue.value.length; i++) {
    const item = +(rangesValue.value[i]);
    // 如果有重复的
    if (item == atPresent) {
      // 重复的下标小于当前下标 当前值 +1
      if (i < index) {
        rangesValue.value[index] = last + 1
      }
      // 重复的下标大于当前下标 当前值 -1
      if(i > index) {
        rangesValue.value[index] = next - 1
      }
    }
  }
  // 设置 || 更新图标区间
  upDateOptionRangesArr()

}
// 手动更新区间数组
const updateRangesValue = (value: number, index: number) => {
  rangesValue.value[index] = value;
};

// 重置规则数组
const resetRanges = () => {
  rangesValue.value = sourceRangesValue.value
  upDateOptionRangesArr()
}

// 新增一条区间
const addRanres = () => {
  rangesValue.value.push(0)
}
// 移除一条区间
const delRangesValue = (item: number,index: number) => {
  if (rangesValue.value.length === 2) return messageApi.error('至少保留一个区间');
  rangesValue.value.splice(index, 1)
  // 设置 || 更新图标区间
  upDateOptionRangesArr()
}

// 筛选类目
const handleSelectChange = (e: number) => {
  if (e == -1) {
    filterList.value = props.dataSource
  }else {
    filterList.value = props.dataSource.filter(item => item.leafCategory == selectValue.value && item.leafCategory != '')
  }
  // 更新图表数据
  if (init.value) return
  setDataSource('update')
}

const changeOptions = () => {
  const arr = []
  for (const key in categoryData) {
    if (Object.hasOwnProperty.call(categoryData, key)) {
      const item = categoryData[key];
      arr.push({
        value: key,
        label: item.path.join(' > ')
      })
    }
  }
  arr.unshift({
    label: '全部',
    value: -1
  })
  selectOption.value = arr
  handleSelectChange(-1)
  setRangesValue(-1,-1)
  setTimeout(() => {
    setDataSource('init')
  },2)
}

watch(() => props.dataSource, () => {
  changeOptions()
}, {
  deep: true,
  immediate: true
})
</script>

<template>
  <div class="shop-type-analysis">
    <context-holder />
    <div class="chart">
      <a-spin :spinning="!showChart">
        <a-select
          style="min-width: 300px;"
          v-model:value="selectValue"
          @change="handleSelectChange"
        >
          <a-select-option
            v-for="item,index in selectOption"
            :key="index"
            :value="item.value"
          >
            {{ item.label }}
          </a-select-option>
        </a-select>
        <div id="myEchart" style="height: 300px;" />
        <div class="input-box">
          <div
            v-for="item,index in rangesValue" 
            :key="index"
            class="input-box"
          >
            <div class="input-item">
              <a-input 
                style="width: 80px;" 
                :value="item" 
                placeholder="区间"
                @input="updateRangesValue($event.target.value, index)" 
                @pressEnter="setRangesValue(item,index)" 
              />
              <PlusCircleOutlined :rotate="50" class="del" @click="delRangesValue(item,index)" />
            </div>
              ~
          </div>
          <div class="placeholder" @click="addRanres">
            +
          </div>
          <button style="background:#409eff;color: #FFFFFF;padding: 7px 15px;border: none;" @click="resetRanges">重置</button>
        </div>
      </a-spin>
    </div>
  </div>
</template>

<style scoped>
.input-box {
  display: flex;
  align-items: center;
  justify-content: center;
}
.placeholder {
  padding: 7px 15px;
  font-size: 12px;
  border-radius: 3px;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #fff;
  border: 1px solid #dcdfe6;
  color: #606266;
  text-align: center;
  margin: 0;
  transition: .1s;
  font-weight: 500;
  margin-right: 10px;
}

.input-item {
  position: relative;
}
.del {
  position: absolute;
  top: -5px;
  right: -5px;
  font-size: 16px;
  display: none;
}

.input-item:hover .del {
  display: block;
}


</style>
